// =============================================
// FD VHS Saturation Crush
// Made by Ubik and Claude 2026
// =============================================
// Simulates VHS saturation degradation:
// saturated colors collapse quadratically
// like aged magnetic tape, with black crush
// that lifts and tints dark areas warm/green.
// Connect video source to video in 1.
// =============================================

// ISADORA_PLUGIN_DESC("VHS Saturation Crush - saturated colors fade like aged tape, with warm/greenish black level lift. Authentic VHS color degradation.")

// ISADORA_FLOAT_PARAM(intensity, inty, 0.0, 1.0, 0.5, "Master intensity - scales all effects. 0 = original, 1 = full degradation.")
// ISADORA_FLOAT_PARAM(saturation_crush, satr, 0.0, 1.0, 0.4, "Saturation collapse - saturated colors fade like aged tape.")
// ISADORA_FLOAT_PARAM(black_crush, blkc, 0.0, 1.0, 0.45, "Lift and tint dark areas warm/greenish - VHS black reproduction.")

uniform float intensity;
uniform float saturation_crush;
uniform float black_crush;
uniform vec3  iResolution;
uniform sampler2D tex0;

vec3 rgb2hsv(vec3 c)
{
    float cmax = max(c.r, max(c.g, c.b));
    float cmin = min(c.r, min(c.g, c.b));
    float delta = cmax - cmin;
    float h = 0.0;
    if (delta > 0.0001)
    {
        if (cmax == c.r)      h = mod((c.g - c.b) / delta, 6.0);
        else if (cmax == c.g) h = (c.b - c.r) / delta + 2.0;
        else                  h = (c.r - c.g) / delta + 4.0;
        h /= 6.0;
        if (h < 0.0) h += 1.0;
    }
    float s = (cmax < 0.0001) ? 0.0 : delta / cmax;
    return vec3(h, s, cmax);
}

vec3 hsv2rgb(vec3 c)
{
    float h = c.x * 6.0;
    float s = c.y;
    float v = c.z;
    float i = floor(h);
    float f = h - i;
    float p = v * (1.0 - s);
    float q = v * (1.0 - s * f);
    float t = v * (1.0 - s * (1.0 - f));
    if (i < 1.0)      return vec3(v, t, p);
    else if (i < 2.0) return vec3(q, v, p);
    else if (i < 3.0) return vec3(p, v, t);
    else if (i < 4.0) return vec3(p, q, v);
    else if (i < 5.0) return vec3(t, p, v);
    else               return vec3(v, p, q);
}

void main()
{
    vec2 uv = gl_FragCoord.xy / iResolution.xy;

    vec4 original = texture2D(tex0, uv);
    vec3 color = original.rgb;

    vec3 hsv = rgb2hsv(color);

    // Saturation Crush: quadratic curve - highly saturated colors collapse harder.
    float crushCurve = hsv.y * hsv.y;
    hsv.y = max(0.0, hsv.y - crushCurve * saturation_crush * intensity * 0.7);

    color = hsv2rgb(hsv);

    // Black Crush: lift and tint shadow areas.
    // Mask targets the bottom 50% of luminance.
    float luma = dot(color, vec3(0.299, 0.587, 0.114));
    float darkMask = clamp(1.0 - luma * 2.0, 0.0, 1.0); // active below 50% luma
    darkMask = darkMask * darkMask;                       // quadratic: smooth falloff
    // Warm green-brown tint - classic worn VHS black level
    color += vec3(0.08, 0.11, 0.05) * darkMask * black_crush * intensity;

    color = clamp(color, 0.0, 1.0);

    gl_FragColor = vec4(color, original.a);
}
